package com.example.demo;

import javafx.animation.*;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.effect.Blend;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.*;
import javafx.scene.text.Text;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
import javafx.util.Duration;

import java.io.IOException;
import java.util.List;

import static javafx.scene.input.KeyCode.SPACE;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        this.waveProess(stage);
    }
    public void autoSinewave(Stage stage){
        //Drawing a Circle
        Circle circle = new Circle();

        //Setting the position of the circle
        circle.setCenterX(300.0f);
        circle.setCenterY(135.0f);

        //Setting the radius of the circle
        circle.setRadius(25.0f);

        //Setting the color of the circle
        circle.setFill(Color.BROWN);

        //Setting the stroke width of the circle
        circle.setStrokeWidth(20);

        //Creating a Path
        Path path = new Path();

        //Moving to the starting point
        MoveTo moveTo = new MoveTo(108, 71);

        //Creating 1st line
        LineTo line1 = new LineTo(321, 161);

        //Creating 2nd line
        LineTo line2 = new LineTo(126,232);

        //Creating 3rd line
        LineTo line3 = new LineTo(232,52);

        //Creating 4th line
        LineTo line4 = new LineTo(269, 250);

        //Creating 5th line
        LineTo line5 = new LineTo(108, 71);

        //Adding all the elements to the path
        path.getElements().add(moveTo);
        path.getElements().addAll(line1, line2, line3, line4, line5);

        //Creating the path transition
        PathTransition pathTransition = new PathTransition();

        //Setting the duration of the transition
        pathTransition.setDuration(Duration.millis(1000));

        //Setting the node for the transition
        pathTransition.setNode(circle);

        //Setting the path for the transition
        pathTransition.setPath(path);

        //Setting the orientation of the path
        pathTransition.setOrientation(
                PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT);

        //Setting the cycle count for the transition
        pathTransition.setCycleCount(50);

        //Setting auto reverse value to true
        pathTransition.setAutoReverse(false);

        //Playing the animation
        pathTransition.play();

        //Creating a Group object
        Group root = new Group(circle);

        //Creating a scene object
        Scene scene = new Scene(root, 600, 300);

        //Setting title to the Stage
        stage.setTitle("Path transition example");

        //Adding scene to the stage
        stage.setScene(scene);

        //Displaying the contents of the stage
        stage.show();
        /*
        //Drawing a Circle
        Circle circle = new Circle();
        //Setting the position of the circle
        circle.setCenterX(300.0f);
        circle.setCenterY(135.0f);
        //Setting the radius of the circle
        circle.setRadius(100.0f);
        //Setting the color of the circle
        circle.setFill(Color.BROWN);
        //Setting the stroke width of the circle
        circle.setStrokeWidth(20);
        //creating stroke transition
        StrokeTransition strokeTransition = new StrokeTransition();
        //Setting the duration of the transition
        strokeTransition.setDuration(Duration.millis(1000));
        //Setting the shape for the transition
        strokeTransition.setShape(circle);
        //Setting the fromValue property of the transition (color)
        strokeTransition.setFromValue(Color.BLACK);
        //Setting the toValue property of the transition (color)
        strokeTransition.setToValue(Color.BROWN);
        //Setting the cycle count for the transition
        strokeTransition.setCycleCount(50);
        //Setting auto reverse value to false
        strokeTransition.setAutoReverse(false);
        //Playing the animation
        strokeTransition.play();
        //Creating a Group object
        Group root = new Group(circle);
        //Creating a scene object
        Scene scene = new Scene(root, 600, 300);
        //Setting title to the Stage
        stage.setTitle("Stroke transition example");
        //Adding scene to the stage
        stage.setScene(scene);
        //Displaying the contents of the stage
        stage.show();*/
        /*
        Circle circle = new Circle();
        //Setting the position of the circle
        circle.setCenterX(150.0f);
        circle.setCenterY(135.0f);
        //Setting the radius of the circle
        circle.setRadius(100.0f);
        //Setting the color of the circle
        circle.setFill(Color.BROWN);
        //Setting the stroke width of the circle
        circle.setStrokeWidth(20);
        //Creating Translate Transition
        TranslateTransition translateTransition = new TranslateTransition();
        //Setting the duration of the transition
        translateTransition.setDuration(Duration.millis(1000));
        //Setting the node for the transition
        translateTransition.setNode(circle);
        //Setting the value of the transition along the x axis.
        translateTransition.setByX(300);
        //Setting the cycle count for the transition
        translateTransition.setCycleCount(50);
        //Setting auto reverse value to false
        translateTransition.setAutoReverse(false);
        //Playing the animation
        translateTransition.play();
        //Creating a Group object
        Group root = new Group(circle);
        //Creating a scene object
        Scene scene = new Scene(root, 600, 300);
        //Setting title to the Stage
        stage.setTitle("Translate transition example");
        //Adding scene to the stage
        stage.setScene(scene);
        //Displaying the contents of the stage
        stage.show();
        */
    }
    public void sinewave(Stage primaryStage){
        Pane pane = new Pane();
        Circle circle = new Circle(15);
        circle.setStroke(Color.PINK);
        circle.setFill(Color.PINK);
        Double[] points=new Double[2000];
        points[0]=0.0;
        points[1]=200.0;
        double d=0.8; //取点间隔
        //生成正弦曲线上的1000个点
        for(int i=2;i<1999;i++){
            points[i]=points[i-2]+d;
            points[i+1]=200+70*Math.sin(points[i]/20);
            i++;
        }

        //用折线逼近正弦曲线
        Polyline polyline = new Polyline();
        polyline.getPoints().addAll(points);
        polyline.setStroke(Color.BLUEVIOLET);
        pane.getChildren().add(circle);
        pane.getChildren().add(polyline);

        //x轴、y轴
        //Line y=new Line(440,0,440,400);
        //Line x=new Line(0,200,800,200);
        Line tick1 = new Line(440,0,435,10);
        Line tick2 = new Line(440,0,445,10);
        Line tick3 = new Line(800,200,790,195);
        Line tick4 = new Line(800,200,790,205);
        //Text texty = new Text(420,10,"Y");
        //Text textx = new Text(780,190,"X");
        //Text textPi1 = new Text(560,210,"2π");
        //Text textPi2 = new Text(300,210,"-2π");
        //Text text0 = new Text(430,210,"0");
        //pane.getChildren().addAll(tick1,tick2,tick3,tick4);
        //pane.getChildren().addAll(textPi1,textPi2,text0);

        PathTransition pt = new PathTransition();
        pt.setPath(polyline);
        pt.setNode(circle);
        pt.setDuration(Duration.seconds(6));
        pt.setOrientation(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT);
        pt.setCycleCount(Timeline.INDEFINITE);
        pt.play();

        circle.setOnKeyPressed(e->{
            if(e.getCode()==SPACE && pt.getStatus()==PathTransition.Status.RUNNING)
                pt.pause();
            else if(e.getCode()==SPACE)
                pt.play();
        });

        Scene scene = new Scene(pane, 800, 400);
        primaryStage.setTitle("The Moving Ball");
        primaryStage.setScene(scene);
        primaryStage.show();
        primaryStage.setResizable(false);
        circle.requestFocus();
    }
    public void ptAnimation(Stage stage) throws IOException {
        Path path = new Path();
        path.getElements().add(new MoveTo(20,20));
        path.getElements().add(new CubicCurveTo(380, 0, 380, 120, 200, 120));
        path.getElements().add(new CubicCurveTo(0, 120, 0, 240, 380, 240));
        // 动画
        final Rectangle rectPath = new Rectangle (0, 0, 40, 40);
        rectPath.setArcHeight(10);
        rectPath.setArcWidth(10);
        rectPath.setFill(Color.ORANGE);
        PathTransition pathTransition = new PathTransition();
        pathTransition.setDuration(Duration.millis(4000));
        pathTransition.setPath(path);
        pathTransition.setNode(rectPath);
        //pathTransition.setOrientation(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT);
        //pathTransition.setCycleCount(Timeline.INDEFINITE);
        pathTransition.setAutoReverse(true);
        pathTransition.play();
        //
        VBox pane = new VBox();
        pane.setStyle("-fx-background-color: #EFEFEF");
        pane.getChildren().addAll(rectPath);
        //pane.getChildren().add(fillPath);
        //
        Scene scene = new Scene(pane, 300, 300);
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }
    public void ballProess(Stage stage) throws IOException {
        // 圆
        Circle circle = new Circle(100,100, 100.00f);
        //circle.setStrokeWidth(1.00f);
        circle.setStroke(Color.BLUE);
        circle.setFill(Color.BLUE);
        // 矩形
        Rectangle emptyRec = new Rectangle();
        emptyRec.setWidth(200.0f);
        emptyRec.setHeight(130.0f);
        emptyRec.setX(0.0f);
        emptyRec.setY(0.0f);
        emptyRec.setFill(Color.BLUE);
        // 裁剪出进度图形
        // intersect: 无所为
        // subtract: 哪个在前少的哪部分在前
        Shape shape = Shape.subtract(circle, emptyRec);
        shape.setFill(Color.BLUE);
        //shape.setStrokeWidth(1);
        shape.setStroke(Color.BLUE);
        // 整体轮廓
        Circle outline = new Circle(0,0, 100.00f);
        outline.setStrokeWidth(2.00f);
        outline.setStroke(Color.BLUE);
        outline.setFill(Color.TRANSPARENT);

        StackPane sp = new StackPane(shape, outline);
        VBox pane = new VBox();
        pane.setStyle("-fx-background-color: #EFEFEF");
        pane.getChildren().add(sp);
        //
        Scene scene = new Scene(pane, 300, 300);
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }
    public void waveProess(Stage stage) throws IOException {
        // FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
        // Scene scene = new Scene(fxmlLoader.load(), 320, 240);
        Circle circle = new Circle(100,100, 100.00f);
        circle.setStrokeWidth(2.00f);
        circle.setStroke(Color.BLUE);
        circle.setFill(Color.WHITE);
        //
        double width = 200.0f;
        double height = 200.0f;
        int progressValue=50;
        //
        Path wavyPath = new Path();
        wavyPath.setStroke(Color.BLUE);
        // wavyPath.setFill(Color.BLUE);
        Group group = new Group(circle);
        // 计算当前值在进度条中高度
        double currentHeight = (1-(progressValue/100.0))*height;
        // 计算圆中有多少个完整周期 这里为1.5个周期
        double roundCycle = (3 * Math.PI) / width;
        // 移动到左下角起始点
        // 指定进度时圆内的直径
        double waveWidth = calcProcessDiameter(progressValue, 200, 100);
        System.out.println("wave width:"+waveWidth);
        // (10,90)=160|(50)=200|(20,80)=180|(30,70)=190|(40,60)=198
        double offsetSize = 100 - (waveWidth / 2);
        // 只有progressValue=50时是x=0
        // wavyPath.getElements().add(new MoveTo(offsetSize, currentHeight));
        // System.out.println("move x:"+offsetSize+",y:"+currentHeight);
        /* 只有progressValue=50时是width=200
        for(double i=offsetSize;i<waveWidth+offsetSize;i++) {
            // 第一条波浪Y轴
            double wavyY1 = (2*Math.sin(roundCycle*i)) + currentHeight;
            if (progressValue == 0) {
                wavyY1 = height;
            }
            if (progressValue == 100) {
                wavyY1 = 0;
            }
            // 添加点在路径中
            wavyPath.getElements().add(new LineTo(i, wavyY1));
            System.out.println("line x:"+i+",y:"+wavyY1);
        }
        */
        // 是否达到了终点
        wavyPath.getElements().add(new MoveTo(offsetSize, currentHeight));
        for(double i=0;i<200;i++) {
            // 第一条波浪Y轴
            double wavyY1 = (5*Math.sin(roundCycle*i)) + currentHeight;
            if (progressValue == 0) {
                wavyY1 = height;
            }
            if (progressValue == 100) {
                wavyY1 = 0;
            }
            // 添加点在路径中
            wavyPath.getElements().add(new LineTo(i, wavyY1));
            System.out.println("line x:"+i+",y:"+wavyY1);
        }
        // 移动到右下角结束点 形成一个闭合路径 后面才能取交集
        // wavyPath.getElements().add(new LineTo(width,height));
        // System.out.println("line x:"+width+",y:"+height);
        group.getChildren().addAll(List.of(wavyPath));
        /* 填充圆
        Ellipse roundPath = new Ellipse();
        roundPath.setCenterX(100.0f);
        roundPath.setCenterY(100.0f);
        roundPath.setFill(Color.BLUE);
        Shape fillPath = Path.intersect(wavyPath, roundPath);*/
        //
        VBox pane = new VBox();
        pane.setStyle("-fx-background-color: #EFEFEF");
        pane.getChildren().addAll(group);
        //pane.getChildren().add(fillPath);
        //
        Scene scene = new Scene(pane, 300, 300);
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }

    /**
     * 计算指定进度值时圆内的直径
     * @param processVal 进度值
     * @param circleDiameter 圆的直径
     * @param circleRadius 圆的半径
     * @return
     */
    public static double calcProcessDiameter(int processVal, int circleDiameter, int circleRadius){
        // i=进度值
        // 进度所占的高度
        double emptyHight = (1-processVal/100.0)*circleDiameter;
        // 根据勾股定理算出当前进度所在圆的直径
        double dwHight = circleRadius - (circleDiameter - emptyHight);
        double i2 = circleRadius*circleRadius - dwHight*dwHight;
        //
        double progessWidth = Math.sqrt(i2) * 2;
        System.out.println("process height="+dwHight+", empty height="+emptyHight+", process="+processVal+", waterline="+progessWidth);
        return progessWidth;
    }
    public static void main(String[] args) {
        launch();
    }
}